package com.rr.sc.model;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import com.rr.sc.model.enums.TransactionType;

@Entity
@Table(name = "transactions")
@SequenceGenerator(name = "transactions_seq", sequenceName = "transactions_seq")
public class Transaction implements Serializable {

	private static final long serialVersionUID = -5240487623199720268L;

	private Long id;
	private Account account;
	private Float value;
	private TransactionType type;
	private Date date;
	private String details;
	private User user;
	private Category category;
	private List<Transaction> subTransactions;
	private Transaction parentTransaction;
	private boolean ignoreInReports;

	@Id
	@GeneratedValue(generator = "transactions_seq", strategy = GenerationType.AUTO)
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
	@JoinColumn(name = "account_id")
	public Account getAccount() {
		return account;
	}

	public void setAccount(Account account) {
		this.account = account;
	}

	@Column(name = "value", nullable = false, columnDefinition = "decimal(14,4)")
	public Float getValue() {
		return value;
	}

	public void setValue(Float value) {
		this.value = value;
	}

	@Column(name = "type", nullable = false)
	public TransactionType getType() {
		return type;
	}

	public void setType(TransactionType type) {
		this.type = type;
	}

	@Column(name = "date")
	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	@Column(name = "details", length = 1000)
	public String getDetails() {
		return details;
	}

	public void setDetails(String details) {
		this.details = details;
	}

	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
	@JoinColumn(name = "user_id", nullable = false)
	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	@ManyToOne(cascade = { CascadeType.MERGE })
	@JoinColumn(name = "category_id")
	public Category getCategory() {
		return category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	/**
	 * @return the subTransactions
	 */
	@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, targetEntity = Transaction.class, mappedBy = "parentTransaction")
	public List<Transaction> getSubTransactions() {
		return subTransactions;
	}

	/**
	 * @param subTransactions
	 *            the subTransactions to set
	 */
	public void setSubTransactions(List<Transaction> subTransactions) {
		this.subTransactions = subTransactions;
	}

	/**
	 * @return the parentTransaction
	 */
	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
	@JoinColumn(name = "parent_transaction_id")
	public Transaction getParentTransaction() {
		return parentTransaction;
	}

	/**
	 * @param parentTransaction
	 *            the parentTransaction to set
	 */
	public void setParentTransaction(Transaction parentTransaction) {
		this.parentTransaction = parentTransaction;
	}

	/**
	 * @return the ignoreInReports
	 */
	@Column(name = "ignore_in_reports", nullable = false, columnDefinition = "tinyint(1)")
	public boolean isIgnoreInReports() {
		return ignoreInReports;
	}

	/**
	 * @param ignoreInReports
	 *            the ignoreInReports to set
	 */
	public void setIgnoreInReports(boolean ignoreInReports) {
		this.ignoreInReports = ignoreInReports;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Transaction [id=").append(id).append(", value=")
				.append(value).append(", date=").append(date)
				.append(", ignore=").append(ignoreInReports)
				.append(", account=").append(account.getName());
		if (category != null) {
			builder.append(", category=").append(category.getName());
		}
		builder.append("]");
		return builder.toString();
	}
}
